package workflow

import (
	"errors"
	"fmt"

	"github.com/jinzhu/gorm"
)

//CallBackFunc 导入过程中触发的回掉函数
type CallBackFunc func(tx *gorm.DB, runID int, userID int) error

//callBackPool 调入前后的回调池
var callBackPool = make(map[string]CallBackFunc, 10)

//SetFinishCallBack 完成后的回调
func SetFinishCallBack(wfid int, cb CallBackFunc) {
	name := fmt.Sprintf("finish_%d", wfid)
	callBackPool[name] = cb
}

//SetCreateCallBack 创建后的回调
func SetCreateCallBack(wfid int, cb CallBackFunc) {
	name := fmt.Sprintf("create_%d", wfid)
	callBackPool[name] = cb
}

//SetBeforeSubmitCallBack 提交前回调
func SetBeforeSubmitCallBack(wfid int, stepId int, cb CallBackFunc) {
	name := fmt.Sprintf("beforeSubmit_%d_%d", wfid, stepId)
	callBackPool[name] = cb
}

func WF1CBF(tx *gorm.DB, runID int, userID int) error {
	return tx.Exec("exec UP_INDI_CLIE_DIVL_PL_NEW ?,?", runID, userID).Error
}

func WF2CBF(tx *gorm.DB, runID int, userID int) error {
	return tx.Exec("exec UP_INDI_CLIE_DIVL_PL_UPDATE ?,?", runID, userID).Error
}

func WF3CBF(tx *gorm.DB, runID int, userID int) error {
	return tx.Exec("exec UP_COMP_CLIE_DIVL_PL_NEW ?,?", runID, userID).Error
}

func WF3CBF_wx(tx *gorm.DB, runID int, userID int) error {
	return tx.Exec("exec UP_COMP_CLIE_DIVL_PL_NEW_WX ?,?", runID, userID).Error
}

func WF4CBF(tx *gorm.DB, runID int, userID int) error {
	return tx.Exec("exec UP_COMP_CLIE_DIVL_PL_UPDATE ?,?", runID, userID).Error
}

func WF1CBF_XJK(tx *gorm.DB, runID int, userID int) error {
	return tx.Exec("exec UP_INDI_CLIE_DIVL_PL_NEW_XJK ?,?", runID, userID).Error
}

func WF1CBF_TXJC(tx *gorm.DB, runID int, userID int) error {
	return tx.Exec("exec UP_MIN_OPER_TXJC_DIVI ?,?", runID, userID).Error
}

func WF2CBF_LS(tx *gorm.DB, runID int, userID int) error {
	return tx.Exec("exec UP_INDI_CLIE_DIVL_PL_UPDATE_LS ?,?", runID, userID).Error
}

func WF2CBF_DF(tx *gorm.DB, runID int, userID int) error {
	return tx.Exec("exec UP_COMP_DFGZ_DIVI ?,?", runID, userID).Error
}

func init() {
	SetFinishCallBack(1, WF1CBF)
	SetFinishCallBack(2, WF2CBF)
	SetFinishCallBack(3, WF3CBF)
	SetFinishCallBack(29, WF3CBF)
	SetFinishCallBack(4, WF4CBF)
	SetFinishCallBack(30, WF4CBF)
	SetFinishCallBack(11, WF1CBF)
	SetFinishCallBack(12, WF2CBF)
	SetFinishCallBack(13, WF3CBF)
	SetFinishCallBack(14, WF4CBF)
	SetFinishCallBack(21, WF1CBF)
	SetFinishCallBack(22, WF2CBF)
	SetFinishCallBack(23, WF3CBF)
	SetFinishCallBack(24, WF4CBF)
	SetFinishCallBack(25, WF1CBF_XJK)
	SetFinishCallBack(27, WF1CBF_TXJC)
	SetFinishCallBack(28, WF2CBF_LS)
	SetFinishCallBack(32, WF2CBF_DF)
	SetFinishCallBack(33, WF2CBF_DF)

}

type GetIdsFunc func(tx *gorm.DB, runid int) error

func GetOrganID(tx *gorm.DB, runid int) (int, error) {
	sql := "select OrgIDx from T_SP_BMBG WHERE FRID=?"
	row := tx.Raw(sql, runid).Row()
	var orgid int
	if err := row.Scan(&orgid); err != nil {
		return 0, err
	}
	return orgid, nil
}

type ExecutorExcludeFunc func(tx *gorm.DB, runid int) (bool, error)

var executorExcludePool = make(map[string]ExecutorExcludeFunc, 10)

type ExecutorFunc func(tx *gorm.DB, runid int) ([]int, error)

var executorPool = make(map[string]ExecutorFunc, 10)

// 零售新客户认定开卡网点负责人
func getIndiKkwdFzrs(tx *gorm.DB, runid int) ([]int, error) {
	sql := "select UTID from T_INDI_CLIE_DIVI3 where FRID=?"
	row := tx.Raw(sql, runid).Row()
	var utid int
	if err := row.Scan(&utid); err != nil {
		return nil, err
	}
	sql = "select COUNT(b.EMID) COUNT from DIM_USER b inner join t_UserRole a on a.UserId=b.EMID where a.RoleId=49 and (b.PDID=? or b.PDID=(select top 1 ParentOrganID from T_Organization where id=?))"
	row = tx.Raw(sql, utid, utid).Row()
	var num int
	row.Scan(&num)
	if num == 0 {
		return nil, errors.New("没有找到网点负责人！")
	}
	sql = "select b.EMID from DIM_USER b inner join t_UserRole a on a.UserId=b.EMID where a.RoleId=49 and (b.PDID=? or b.PDID=(select top 1 ParentOrganID from T_Organization where id=?))"
	row = tx.Raw(sql, utid, utid).Row()
	var emid int
	if err := row.Scan(&emid); err != nil {
		return nil, err
	}
	if emid == 0 {
		return nil, errors.New("没有找到网点负责人！")
	}
	return []int{emid}, nil
}

// 零售新客户认定开卡网点负责人(小京卡)
func getIndiKkwdFzrsXJK(tx *gorm.DB, runid int) ([]int, error) {
	sql := "select UTID from T_INDI_CLIE_DIVI_XJK where FRID=?"
	row := tx.Raw(sql, runid).Row()
	var utid int
	if err := row.Scan(&utid); err != nil {
		return nil, err
	}
	sql = "SELECT COUNT(*) COUNT FROM V_ParentOrgan where ParentOrganID in(61,80) AND OrganID=?"
	row = tx.Raw(sql, utid).Row()
	var reg int
	if err := row.Scan(&reg); err != nil {
		return nil, err
	}
	var emid int
	if reg == 0 {
		sql = "select COUNT(b.EMID) COUNT from DIM_USER b inner join t_UserRole a on a.UserId=b.EMID where a.RoleId=49 and (b.PDID=? or b.PDID=(select top 1 ParentOrganID from T_Organization where id=?))"
		row = tx.Raw(sql, utid, utid).Row()
		var num int
		row.Scan(&num)
		if num == 0 {
			return nil, errors.New("没有找到网点负责人！")
		}
		sql = "select b.EMID from DIM_USER b inner join t_UserRole a on a.UserId=b.EMID where a.RoleId=49 and (b.PDID=? or b.PDID=(select top 1 ParentOrganID from T_Organization where id=?))"
		row = tx.Raw(sql, utid, utid).Row()

		if err := row.Scan(&emid); err != nil {
			return nil, err
		}
		if emid == 0 {
			return nil, errors.New("没有找到网点负责人！")
		}
	} else {
		sql = "select b.EMID from DIM_USER b inner join t_UserRole a on a.UserId=b.EMID where a.RoleId=102 and (b.PDID=? or b.PDID=(select top 1 ParentOrganID from T_Organization where id=?))"
		row = tx.Raw(sql, utid, utid).Row()

		if err := row.Scan(&emid); err != nil {
			return nil, err
		}
		if emid == 0 {
			return nil, errors.New("没有找到网点负责人！")
		}
	}
	return []int{emid}, nil
}

// 零售新客户认定管户人(小京卡)
func getIndiGhrXJK(tx *gorm.DB, runid int) ([]int, error) {
	sql := "SELECT EMID2 FROM T_INDI_CLIE_DIVI_XJK WHERE FRID=?"
	rows, err := tx.Raw(sql, runid).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 零售变更原客户经理所在经营单位负责人审批
func getIndiAcidFzrs(tx *gorm.DB, runid int) ([]int, error) {
	sql := "select CUID from T_INDI_CLIE_DIVI2  where FRID=? "
	row := tx.Raw(sql, runid).Row()
	var acid int
	if err := row.Scan(&acid); err != nil {
		return nil, err
	}
	sql = "select b.EMID from DIM_USER b inner join t_UserRole a on a.UserId=b.EMID where a.RoleId=49 and b.PDID in (select b.PDID from T_INDI_ACCO_DIVI A INNER JOIN DIM_USER B  on a.EMID=b.EMID where ACID IN (select ID from T_INDI_ACCO where CUID=?) AND ISWO=0 AND WODT IS NULL)"
	rows, err := tx.Raw(sql, acid).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 零售变更原客户经理所在经营单位负责人审批(二级分行)
func getIndiAcidFzrs2(tx *gorm.DB, runid int) ([]int, error) {
	sql := "select CUID from T_INDI_CLIE_DIVI2  where FRID=? "
	row := tx.Raw(sql, runid).Row()
	var acid int
	if err := row.Scan(&acid); err != nil {
		return nil, err
	}
	sql = "select b.EMID from DIM_USER b inner join t_UserRole a on a.UserId=b.EMID where a.RoleId=109 and b.DPID in (select b.DPID from T_INDI_ACCO_DIVI A INNER JOIN DIM_USER B on a.EMID=b.EMID where ACID IN (select ID from T_INDI_ACCO where CUID=?) AND ISWO=0 AND WODT IS NULL)"
	rows, err := tx.Raw(sql, acid).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 对公变更原客户经理所在经营单位负责人审批
func getCompAcidFzrs(tx *gorm.DB, runid int) ([]int, error) {
	sql := " select ACID from T_COMP_CLIE_DIVI2  where FRID=?"
	row := tx.Raw(sql, runid).Row()
	var id int
	if err := row.Scan(&id); err != nil {
		return nil, err
	}
	sql = " select b.EMID from DIM_USER b inner join t_UserRole a on a.UserId=b.EMID where a.RoleId=41 and b.PDID in (select b.PDID from T_COMP_ACCO_DIVI A INNER JOIN DIM_USER B  on a.EMID=b.EMID where ACID=? AND ISWO=0 AND WODT IS NULL)"
	rows, err := tx.Raw(sql, id).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 对公变更原客户经理所在经营单位负责人审批(二级分行)
func getCompAcidFzrs2(tx *gorm.DB, runid int) ([]int, error) {
	sql := " select ACID from T_COMP_CLIE_DIVI2  where FRID=?"
	row := tx.Raw(sql, runid).Row()
	var id int
	if err := row.Scan(&id); err != nil {
		return nil, err
	}
	sql = " select b.EMID from DIM_USER b inner join t_UserRole a on a.UserId=b.EMID where a.RoleId in(41,109) and b.DPID in (select b.DPID from T_COMP_ACCO_DIVI A INNER JOIN DIM_USER B  on a.EMID=b.EMID where ACID=? AND ISWO=0 AND WODT IS NULL)"
	rows, err := tx.Raw(sql, id).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 对公业绩变更审批流程原客户经理审批
func getCompYkhjl(tx *gorm.DB, runid int) ([]int, error) {
	sql := " select ACID from T_COMP_CLIE_DIVI2  where FRID=?"
	row := tx.Raw(sql, runid).Row()
	var id int
	if err := row.Scan(&id); err != nil {
		return nil, err
	}
	sql = "select b.EMID from T_COMP_ACCO_DIVI A INNER JOIN DIM_USER B on a.EMID=b.EMID where ACID=? AND ISWO=0 AND WODT IS NULL"
	rows, err := tx.Raw(sql, id).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 零售变更原客户经理
func getIndiYkhjl(tx *gorm.DB, runid int) ([]int, error) {
	sql := "select CUID from T_INDI_CLIE_DIVI2  where FRID=? "
	row := tx.Raw(sql, runid).Row()
	var acid int
	if err := row.Scan(&acid); err != nil {
		return nil, err
	}
	sql = "select b.emid from T_INDI_ACCO_DIVI A INNER JOIN DIM_USER B on a.EMID=b.EMID where a.ACID IN (select ID from T_INDI_ACCO where CUID=?) AND a.ISWO=0 AND a.WODT IS NULL"
	rows, err := tx.Raw(sql, acid).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 零售新客户相关客户经理业绩确认审批
func getIndiSqXgFzrs(tx *gorm.DB, runid int) ([]int, error) {
	sql := "SELECT EMID FROM V_INDI_CLIE_DIVI3 WHERE FRID=?"
	rows, err := tx.Raw(sql, runid).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 零售变更审批相关客户经理业绩确认审批
func getIndiBgXgFzrs(tx *gorm.DB, runid int) ([]int, error) {
	sql := "SELECT EMID FROM V_INDI_CLIE_DIVI2 WHERE FRID=?"
	rows, err := tx.Raw(sql, runid).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 公司新客户相关客户经理业绩确认审批
func getCompSqXgFzrs(tx *gorm.DB, runid int) ([]int, error) {
	sql := "SELECT EMID FROM V_COMP_CLIE_DIVI WHERE FRID=?"
	rows, err := tx.Raw(sql, runid).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 公司客户变更相关客户经理业绩确认审批
func getCompBgXgFzrs(tx *gorm.DB, runid int) ([]int, error) {
	sql := "SELECT EMID FROM V_COMP_CLIE_DIVI2 WHERE FRID=?"
	rows, err := tx.Raw(sql, runid).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 贴现价差中收相关客户经理业绩确认审批
func getCompTxjcFzrs(tx *gorm.DB, runid int) ([]int, error) {
	sql := "SELECT EMID FROM V_MIN_OPER_TXJC_DIVI WHERE FRID=?"
	rows, err := tx.Raw(sql, runid).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 代发工资相关客户经理业绩确认审批
func getCompDfgzFzrs(tx *gorm.DB, runid int) ([]int, error) {
	sql := `SELECT EMID FROM (
		SELECT EMID1 EMID,FRID 
		FROM T_COMP_DFGZ_RD WHERE EMID1>0
		UNION ALL
		SELECT EMID2,FRID 
		FROM T_COMP_DFGZ_RD WHERE EMID2>0
		UNION ALL
		SELECT EMID3,FRID 
		FROM T_COMP_DFGZ_RD WHERE EMID3>0
		UNION ALL
		SELECT EMID4,FRID 
		FROM T_COMP_DFGZ_RD WHERE EMID4>0
		UNION ALL
		SELECT EMID5,FRID 
		FROM T_COMP_DFGZ_RD WHERE EMID5>0
		) A WHERE FRID=?`
	rows, err := tx.Raw(sql, runid).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 代发工资相关客户经理业绩确认审批
func getCompDfgzFzrs2(tx *gorm.DB, runid int) ([]int, error) {
	sql := `SELECT EMID FROM (
		SELECT EMID1 EMID,FRID 
		FROM T_COMP_DFGZ_RD_UPDATE WHERE EMID1>0
		UNION ALL
		SELECT EMID2,FRID 
		FROM T_COMP_DFGZ_RD_UPDATE WHERE EMID2>0
		UNION ALL
		SELECT EMID3,FRID 
		FROM T_COMP_DFGZ_RD_UPDATE WHERE EMID3>0
		UNION ALL
		SELECT EMID4,FRID 
		FROM T_COMP_DFGZ_RD_UPDATE WHERE EMID4>0
		UNION ALL
		SELECT EMID5,FRID 
		FROM T_COMP_DFGZ_RD_UPDATE WHERE EMID5>0
		) A WHERE FRID=?`
	rows, err := tx.Raw(sql, runid).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 代发工资更审批流程原客户经理审批
func getCompDfgzYkhjl(tx *gorm.DB, runid int) ([]int, error) {
	sql := " select DWBH from T_COMP_DFGZ_RD_UPDATE  where FRID=?"
	row := tx.Raw(sql, runid).Row()
	var dwbh string
	if err := row.Scan(&dwbh); err != nil {
		return nil, err
	}
	sql = "select b.EMID from T_COMP_DFGZ_DIVI A INNER JOIN DIM_USER B on a.EMID=b.EMID where DWBH=? AND ISWO=0 AND WODT IS NULL"
	rows, err := tx.Raw(sql, dwbh).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 代发工资更审原客户经理所在经营单位负责人审批
func getCompDfgzYkhjlFzrs(tx *gorm.DB, runid int) ([]int, error) {
	sql := " select DWBH from T_COMP_DFGZ_RD_UPDATE  where FRID=?"
	row := tx.Raw(sql, runid).Row()
	var dwbh string
	if err := row.Scan(&dwbh); err != nil {
		return nil, err
	}
	sql = " select b.EMID from DIM_USER b inner join t_UserRole a on a.UserId=b.EMID where a.RoleId in(9,41,109) and b.DPID in (select b.DPID from T_COMP_DFGZ_DIVI A INNER JOIN DIM_USER B  on a.EMID=b.EMID where DWBH=? AND ISWO=0 AND WODT IS NULL)"
	rows, err := tx.Raw(sql, dwbh).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 获取计财部负责人
func getjcFzrs(tx *gorm.DB, runid int) ([]int, error) {
	sql := "SELECT EMID FROM DIM_USER WHERE EMID in(select UserId from t_UserRole where RoleId=41) AND DPNM='计划财务部'"
	rows, err := tx.Raw(sql).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

// 获取计财部负责人
func getSysDev(tx *gorm.DB, runid int) ([]int, error) {
	sql := "SELECT ID EMID FROM T_SysUser WHERE SysUserID='888888'"
	rows, err := tx.Raw(sql).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	emids := make([]int, 0, 3)
	for rows.Next() {
		var emid int
		rows.Scan(&emid)
		emids = append(emids, emid)
	}
	return emids, nil
}

func init() {
	executorPool["@getIndiAcidFzrs"] = getIndiAcidFzrs
	executorPool["@getIndiKkwdFzrs"] = getIndiKkwdFzrs
	executorPool["@getCompAcidFzrs"] = getCompAcidFzrs
	executorPool["@getIndiAcidFzrs2"] = getIndiAcidFzrs2
	executorPool["@getCompAcidFzrs2"] = getCompAcidFzrs2
	executorPool["@getCompYkhjl"] = getCompYkhjl
	executorPool["@getIndiYkhjl"] = getIndiYkhjl
	executorPool["@getIndiKkwdFzrsXJK"] = getIndiKkwdFzrsXJK
	executorPool["@getIndiGhrXJK"] = getIndiGhrXJK

	executorPool["@getIndiSqXgFzrs"] = getIndiSqXgFzrs
	executorPool["@getIndiBgXgFzrs"] = getIndiBgXgFzrs
	executorPool["@getCompSqXgFzrs"] = getCompSqXgFzrs
	executorPool["@getCompBgXgFzrs"] = getCompBgXgFzrs
	executorPool["@getCompTxjcFzrs"] = getCompTxjcFzrs
	executorPool["@getCompDfgzFzrs"] = getCompDfgzFzrs
	executorPool["@getCompDfgzFzrs2"] = getCompDfgzFzrs2
	executorPool["@getCompDfgzYkhjl"] = getCompDfgzYkhjl
	executorPool["@getCompDfgzYkhjlFzrs"] = getCompDfgzYkhjlFzrs
	executorPool["@getjcFzrs"] = getjcFzrs
	executorPool["@getSysDev"] = getSysDev
}
